package dm_tool
{
	import dm_tool.enums.CharacterSequence;
	import dm_tool.enums.CharacterStatus;
	
	import mx.collections.ArrayCollection;
	import mx.collections.Sort;
	import mx.collections.SortField;
	import mx.controls.Alert;
	import mx.core.Application;
	
	public class DmTool
	{
		/**
		 * -1, if a should appear before b in the sorted sequence
	     * 0, if a equals b
	     * 1, if a should appear after b in the sorted sequence
	     * 
	     * All possible states:
	     * Sequence.Active
	     * 
	     * Sequence.Waiting && Turn == Current && InitiativeTotal > 
	     * Sequence.Waiting && Turn == Current && InitiativeTotal < 
	     * Sequence.Waiting && Turn == Current && InitiativeTotal == 
	     * 
	     * Sequence.Delaying && Turn == Current && InitiativeTotal > 
	     * Sequence.Delaying && Turn == Current && InitiativeTotal < 
	     * Sequence.Delaying && Turn == Current && InitiativeTotal == 
	     * 
	     * Sequence.Reading && Turn == Current && InitiativeTotal > 
	     * Sequence.Reading && Turn == Current && InitiativeTotal < 
	     * Sequence.Reading && Turn == Current && InitiativeTotal == 
	     * 
 	     * Sequence.Waiting && Turn == Next && InitiativeTotal > 
	     * Sequence.Waiting && Turn == Next && InitiativeTotal < 
	     * Sequence.Waiting && Turn == Next && InitiativeTotal ==
	     *  
	     * Sequence.Reserve
		 **/
		 
		public static function SortCombatants(combatants:ArrayCollection):ArrayCollection
		{
			var sort:Sort = new Sort();
			sort.fields = [new SortField("InitiativeTotal", false, true)];
			
			//Final sorted combatants
			var sortedCombatants:ArrayCollection = new ArrayCollection();
			
			//Arrays we sort into
			var combatantsActive:ArrayCollection = new ArrayCollection();
			var combatantsWaitingCurrent:ArrayCollection = new ArrayCollection();
			combatantsWaitingCurrent.sort = sort;
			var combatantsDelayedCurrent:ArrayCollection = new ArrayCollection();
			combatantsDelayedCurrent.sort = sort;
			var combatantsReadyingCurrent:ArrayCollection = new ArrayCollection();
			combatantsReadyingCurrent.sort = sort;
			var combatantsWaitingNext:ArrayCollection = new ArrayCollection();
			combatantsWaitingNext.sort = sort;
			var combatantsReserved:ArrayCollection = new ArrayCollection();
			combatantsReserved.sort = sort;
			var combatantsDead:ArrayCollection = new ArrayCollection();
			combatantsDead.sort = sort;
			
			var character:Character = null;
			
			//Iterate over and split them into seperate collections
			for each (character in combatants)
			{
				
				if (character.Status == CharacterStatus.Dead)
				{
					//Sort out the dead characters first
					combatantsDead.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Active)
				{
					//Active characters at the top
					combatantsActive.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Waiting && character.Turn <= Application.application.currentCombatRound)
				{
					//Waiting characters this turn
					combatantsWaitingCurrent.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Delaying)
				{
					//Delayed characters this turn
					combatantsDelayedCurrent.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Readying)
				{
					//Reading characters this turn
					combatantsReadyingCurrent.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Waiting && character.Turn > Application.application.currentCombatRound)
				{
					//Next turn characters
					combatantsWaitingNext.addItem(character);
				}
				else if (character.Sequence == CharacterSequence.Reserve)
				{
					//Reserve characters
					combatantsReserved.addItem(character);
				}
				else
				{
					//Should not ever get here
					Alert.show(character.Name+" did not get sorted Sequence: "+character.Sequence+" Turn: "+character.Turn+"  CurrentCombatRound: "+Application.application.currentCombatRound);
				}
			}
			
			//Force the sort
			combatantsActive.refresh();
			combatantsWaitingCurrent.refresh();
			combatantsWaitingCurrent.refresh();
			combatantsReadyingCurrent.refresh();
			combatantsWaitingNext.refresh();
			combatantsReserved.refresh();
			combatantsDead.refresh();
			
			//Re-combine the characters
			for each (character in combatantsActive)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsWaitingCurrent)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsDelayedCurrent)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsReadyingCurrent)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsWaitingNext)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsReserved)
			{
				sortedCombatants.addItem(character);
			}
			for each (character in combatantsDead)
			{
				sortedCombatants.addItem(character);
			}
			
			return sortedCombatants;
		}
		
		/** Static Methods **/
		public static function CalculateCharacterStatus(character:Character):String
		{
			Application.application.logDebug("CalculateCharacterStatus()");
			
			var healthPercent:Number = (character.HitPointsCurrent + character.HitPointsTemp) / character.HitPoints;
			var status:String = CharacterStatus.Ok;
						
			if (healthPercent <= 0.5)
			{
				status = CharacterStatus.Bloody;
			}
			
			return status;
		}
		
		public static function randomNumber(low:Number=NaN, high:Number=NaN):Number
		{
			var low:Number = low;
			var high:Number = high;
			
			if(isNaN(low))
			{
				throw new Error("low must be defined");
			}
			if(isNaN(high))
			{
				throw new Error("high must be defined");
			}
			
			return Math.round(Math.random() * (high - low)) + low;
		}
		
		public static function CreateDemoCombatants(PcCount:int, NpcCount:int):ArrayCollection
		{
			var combatants:ArrayCollection = new ArrayCollection();
			var character:Character = null;

			var i:int;
			
			for (i = 0;i < PcCount;i++)
			{
				character = new Character();
				character.Id = "PC"+i;
				character.Name = "PC "+i;
				character.DeathSavesCount = 3;
				character.DeathSavesUsed = 0;
				character.HealingSurges = 6;
				character.HitPoints = DmTool.randomNumber(26,50);
				character.HitPointsCurrent = character.HitPoints;
				character.HitPointsTemp = 0;
				character.Initiative = DmTool.randomNumber(0,4);
				character.Ac = DmTool.randomNumber(10,18);
				character.FortitudeDefense = DmTool.randomNumber(10,18);
				character.ReflexDefense = DmTool.randomNumber(10,18);
				character.WillpowerDefense = DmTool.randomNumber(10,18);
				character.isPc = true;
				character.Status = CharacterStatus.Ok;
				character.Sequence = CharacterSequence.Reserve;
				character.Reserve = false;
				
				combatants.addItem(character);
			}
			
			for (i = 0;i < NpcCount;i++)
			{
				character = new Character();
				character.Id = "NPC"+i;
				character.Name = "NPC "+i;
				character.DeathSavesCount = 3;
				character.DeathSavesUsed = 0;
				character.HealingSurges = 6;
				character.HitPoints = DmTool.randomNumber(26,50);
				character.HitPointsCurrent = character.HitPoints;
				character.HitPointsTemp = 0;
				character.Initiative = DmTool.randomNumber(0,4);
				character.Ac = DmTool.randomNumber(10,18);
				character.FortitudeDefense = DmTool.randomNumber(10,18);
				character.ReflexDefense = DmTool.randomNumber(10,18);
				character.WillpowerDefense = DmTool.randomNumber(10,18);
				character.isPc = false;
				character.Status = CharacterStatus.Ok;
				character.Sequence = CharacterSequence.Reserve;
				character.Reserve = false;
				character.isMinion = false;
				
				combatants.addItem(character);
			}
			
			
			
			
			return combatants;
		}
	}
}